const { IntentCreep, CreepBehavior, Behavior} = require('./Overtick');
const { Util, COLOR } = require('./Util');
let u = Util;

let RoleType = {
    Harvester:"Harvester",
    Transfer:"Transfer",
    Upgrader:"Upgrader",
    Fixer:"Fixer",
}

/**
 * 为房间提供注册，位置预定功能
 */
let RoomManager = class RoomManager{

    loop(){

        //静态信息扫描
        if(this.isRoomLengthChange()){
            let rooms = this.getChangeRooms();
            for(let room of rooms){
                let staticdata = this.scanStaticRoom(room);
                Memory.Homestead.RoomManager.rooms[room.name] = staticdata;
            }
        }

        //动态信息扫描
        if(Game.time % 50 == 0){
            for(let roomName in Game.rooms){
                let room = Game.rooms[roomName];
                let dynamicdata = this.scanDynamicRoom(room);
                if(Memory.Homestead.RoomManager.rooms[room.name] == undefined){
                    Memory.Homestead.RoomManager.rooms[room.name] = {};
                }
                Memory.Homestead.RoomManager.rooms[room.name] = Object.assign(Memory.Homestead.RoomManager.rooms[room.name],dynamicdata);
            }


            //处理已经不存在或过期的数据
            //TODO
        }

        //渲染数据
        for(let roomName in Memory.Homestead.RoomManager.rooms){
            let data = Memory.Homestead.RoomManager.rooms[roomName];
            let v = new RoomVisual(roomName);

            if(data.containers != undefined){
                for(let id in data.containers){
                    let container = data.containers[id];
                    let t;
                    switch(container.type){
                        case 2:t = "I";break;
                        case 0:t = "A";break;
                        case 1:t = "O";break;
                        case -1:t = "A";break;
                    }
                    v.text(t,container.x,container.y+0.25,{
                        font:0.5
                    });
                }
            }

        }
    }


    /**
     * 获取并预定一个Source开采位置
     */
    getHarvestLocation(source){
        if(!(source instanceof Source || source instanceof Mineral)){
            throw TypeError();
        }

        let center = source.pos;

        //获取3*3范围内的可用工位
        let data = source.room.lookAtArea(
            center.y-1,center.x-1,
            center.y+1,center.x+1);

        let workPos = [];

        let canWorking = function(things){
            for(let item of things){
                if(item.type == "terrain" && item.terrain == "wall"){
                    return false;
                }
            }

            return true;
        }

        for(let y in data){
            for(let x in data[y]){
                if(canWorking(data[y][x])){
                    workPos.push({
                        x:x,
                        y:y
                    })
                }
            }
        }

        return workPos;
    }

    isRoomLengthChange(){
        let rooms = Memory.Homestead.RoomManager.rooms;

        let o = Object.keys(rooms).length;
        let n = Object.keys(Game.rooms).length;
        
        return o != n;
    }

    getChangeRooms(){
        let buffer = []
        let rooms = Memory.Homestead.RoomManager.rooms;
        for(let roomName in Game.rooms){
            if(!rooms.hasOwnProperty(roomName)){
                buffer.push(Game.rooms[roomName]);
            }
        }

        return buffer;
    }

    scanStaticRoom(room){//扫描房间静态信息
        //定位所有Source Harvest Position
        let res = {
            sources:{
                // someid:{
                //     x:0,
                //     y:0,
                //     harvestPos:[]
                // }
            },
            mineral:{
                // someid:{
                //     x:0,
                //     y:0,
                //     harvestPos:[]
                // }
            },
        }
        let sources = room.find(FIND_SOURCES);
        for(let source of sources){
            res.sources[source.id] = {
                x:source.pos.x,
                y:source.pos.y,
                harvestPos:this.getHarvestLocation(source)
            }
        }

        let minerals = room.find(FIND_MINERALS);
        for(let mineral of minerals){
            res.mineral[mineral.id] = {
                x:mineral.pos.x,
                y:mineral.pos.y,
                harvestPos:this.getHarvestLocation(mineral)
            }
        }


        return res;
    }

    scanDynamicRoom(room){
        let res = {
            containers:{
                // someid:{
                //     x:0,
                //     y:0,
                //     type:in(1)/out(2)/all(0)
                // }
            }
        }

        let containers = room.find(FIND_STRUCTURES,{
            filter:function(obj){
                return obj instanceof StructureContainer;
            }
        });
        let sources = room.find(FIND_SOURCES);
        let minerals = room.find(FIND_MINERALS);
        for(let i of containers){
            //判断类型，如果旁边有 sources/minerals 则为1，有Controller则为2，都有就是0，孤立的则是-1
            let hasSOM = false;//sources/minerals
            let hasC = false;//Controller

            for(let j of sources){
                if(j.pos.getRangeTo(i) <= 2){
                    hasSOM = true;break;
                }
            }
            for(let j of minerals){
                if(j.pos.getRangeTo(i) <= 2){
                    hasSOM = true;break;
                }
            }

            if(room.controller != undefined){
                if(i.pos.getRangeTo(room.controller) <= 3){
                    hasC = true;
                }
            }

            if(hasSOM && hasC){
                res.containers[i.id] = {
                    x:i.pos.x,
                    y:i.pos.y,
                    type:0
                }
            }else if(hasSOM){
                res.containers[i.id] = {
                    x:i.pos.x,
                    y:i.pos.y,
                    type:1
                }
            }else if(hasC){
                res.containers[i.id] = {
                    x:i.pos.x,
                    y:i.pos.y,
                    type:2
                }
            }else{
                res.containers[i.id] = {
                    x:i.pos.x,
                    y:i.pos.y,
                    type:-1
                }
            }
        }
        return res;
    }

    getRoomData(roomName){
        if(roomName instanceof Room){
            roomName = roomName.name;
        }
        return u.mget(() => Memory.Homestead.RoomManager.rooms[roomName],{})
    }
    
    //=============================== Console API =====================
    //绑定creep到一个Source
    bindCreepToSource(name,source){
        //检查类型
        let info = HS.getCreepInfo(name);
        if(info.type != RoleType.Harvester){
            u.log(`${name} 的类型不是 Harvester，不能绑定 Source`,{
                color:COLOR.RED
            });
            return false;
        }

        if(source == undefined){
            u.log(`不是一个有效的 Source 对象`,{
                color:COLOR.RED
            });
            return false;
        }

        if(source.constructor.name == "String"){

        }else if(source instanceof Source){
            source = source.id;
        }else{
            u.log(`不是一个有效的 Source 对象`,{
                color:COLOR.RED
            });
            return false;
        }

    
    }


}
let _RoomManager = new RoomManager();
//TODO CRS 联网检查版本
let Homestead = class Homestead{
    constructor(){
        this.version = 10;

        this.overtickCreeps = {};

        this.main = undefined;

        this.initMemory();
        u.log(`《HomeStead》 初始化完成 版本：${this.version} <a>点击检查更新</a>`,{
            color:COLOR.YELLOW
        })
    }
    initMemory(){
        //存放Homestead数据的Memory位置，请务必设为Memory下的路径
        let memoryConfig = [
            "Memory.Homestead",
            "Memory.Homestead.creeps",
            "Memory.Homestead.RoleType",
            "Memory.Homestead.RoomManager",
        ]
        //建文件夹
        for(let path of memoryConfig){
            if(u.mget(path) == undefined){
                u.mset(path,{});
            }
        }
        Memory.Homestead.version = this.version;     
    }

    loop(){
        let listenName = "Jem"
        if(this.overtickCreeps[listenName] instanceof IntentCreep){
            this.overtickCreeps[listenName].printStack();
        }

        //遍历creep 创建 Overtick 实体
        for(let creepName in Memory.Homestead.creeps){
            //检查有无实体
            if(this.overtickCreeps[creepName] == undefined){
                this.overtickCreeps[creepName] = new IntentCreep(creepName);
            }
        }

        //交给 main
        if(this.main != undefined){
            new (this.main)(this,[this.overtickCreeps]);
        }

        _RoomManager.loop();
    }

    //=============================== Console API =====================
    /**
     * 
     * @param {String} name Creep 的名称
     * @param {*} body Creep 的Body {"move":1,"work":1}
     */
    addCreep(name,type,roomName,body = {'work':1,'carry':1,'move':1}){

        if(name == undefined){
            throw ReferenceError("需要一个名称");
        }

        if(type == undefined){
            throw ReferenceError("需要一个类型");
        }

        if(roomName == undefined){
            throw ReferenceError("需要设置房间")
        }
        
        let creeps = Memory.Homestead.creeps;

        if(creeps[name] == undefined){
            u.log(`${name} 已加入游戏\n类型:${type}\n部件:${JSON.stringify(body)}\n所属房间:${roomName}`,{
                color:COLOR.GREEN,
            })
        }else{
            u.log(`${name} 已更新\n类型:${type}\n部件:${JSON.stringify(body)}\n所属房间:${roomName}`,{
                color:COLOR.GREEN,
            })
        }

        creeps[name] = {
            type:type,
            roomName:roomName,
            body:body
        }

        
    }

    setCreepBodyNum(name,body,num = 0){
        let creeps = Memory.Homestead.creeps;

        if(creeps[name] == undefined){
            u.log(`${name} 不存在`,{
                color:COLOR.RED,
            });
            return;
        }

        if(body == undefined){
            u.log(`${body} 不是一个有效的body`,{
                color:COLOR.RED,
            });
            return;
        }

        creeps[name].body[body] = num;

        u.log(`${name} 已更新\n类型:${creeps[name].type}\n部件:${JSON.stringify(creeps[name].body)}\n所属房间:${creeps[name].roomName}`,{
            color:COLOR.GREEN,
        })
        return;
    }

    getCreepInfo(a1){
        let name;
        if(a1.constructor.name == "String"){
            name = a1;
        }else if(a1 instanceof CreepBehavior){
            name = a1.getCreepName();
        }
        return Memory.Homestead.creeps[name];
    }

    getCreepType(a1){
        let info = this.getCreepInfo(a1);
        if(info != undefined){
            return info.type;
        }
    }

    getCreepRoomName(a1){
        let info = this.getCreepInfo(a1);
        if(info != undefined){
            return info.roomName;
        }
    }

    getCreepRoom(a1){
        let roomName = this.getCreepRoomName(a1);
        if(roomName != undefined){
            return Game.rooms[roomName] || undefined;
        }
    }

    /**
     * 获取Creep的Body
     * @param {} name Creep 的名字
     * @param {*} zip 是否压缩，默认false
     * @returns 
     */
    getCreepBody(name,zip=false){
        let info = this.getCreepInfo(name);
        if(info != undefined){
            if(zip){
                return info.body;
            }else{
                return u.unzipBody(info.body);
            }
        }
    }

    getCreepBodyNum(a1,type){
        let info = this.getCreepInfo(a1);
        if(info != undefined){
            return u.unzipBody(info.body);
        }
    }

    getCreepsInfoByRoom(room){
        let roomName;
        if(room instanceof Room){
            roomName = room.name;
        }

        let creeps = Memory.Homestead.creeps;
        let buffer = {};
        for(let name in creeps){
            if(creeps[name].roomName == roomName){
                buffer[name] = creeps[name];
            }
        }
        return buffer;
    }

    setMain(behavior){
        if(Behavior.isPrototypeOf(behavior)){
            this.main = behavior;
        }
    }
}
let HS = new Homestead();




u.setPrototype(Room,{
    addCreep:function(name,type,body){
        HS.addCreep(name,type,this.name,body);
    },
    getCreepsInfo:function(){
        return HS.getCreepsInfoByRoom(this);
    },
})

u.setPrototype(Creep,{

    //Harvester
    bindHarvestPos:function(source){
        _RoomManager.bindCreepToSource(this.name,source);
    },
    getHarvestPos:function(){

    }

})



_RoomManager.scanDynamicRoom(Game.rooms.E56S28);

global.HS = HS;
module.exports.HS = HS;
module.exports.RoleType = RoleType;
module.exports.RoomManager = _RoomManager;